package com.ag.utils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.ParserConfig;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.util.TypeUtils;

/**
 * Json帮助类 
 * 
 * @author rplees
 * @email rplees.i.ly@gmail.com
 * @version 1.0  
 * @created Mar 17, 2021 1:18:09 PM
 */
public class Jsons {
	/**
	 * o->JSON 
	 * 如果o为空, 或者是非法JSON格式, 则返回 new JSONObject
	 * @param str
	 * @return
	 */
	public static JSONObject toJSONAnyway(Object o) {
		try {
			JSONObject json = toJSON(o);
			return json != null ? json : new JSONObject();
		} catch(Exception e) {
			return new JSONObject();
		}
	}
	
	public static JSONObject toJSON(Object o) {
		return toJSON(o, new SerializerFeature[] {});
	}
	
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static JSONObject toJSON(Object o, SerializerFeature... features) {
		if(o == null) {
			return null;
		}
		
		if(o instanceof JSONObject) {
			return (JSONObject) o;
		} else if(o instanceof String) {
			String str = (String) o;
			if(StringUtils.isBlank(str)) {
				return null;
			}
			return JSON.parseObject(str);
		} else if(o instanceof Map) {
			return new JSONObject((Map) o);
		}
		
		if(CollectionUtils.isEmpty(features)) {
			return JSON.parseObject(JSON.toJSONString(o));
		}
		
		return JSON.parseObject(JSON.toJSONString(o, features));
	}
	
	public static <T> T toBean(String json, Class<T> clazz) {
		return getByPath(json, null, clazz);
	}
	
	public static <T> T toBean(JSONObject json, Class<T> clazz) {
		return getByPath(json, null, clazz);
	}
	
	public static <T> List<T> toListAnyway(String list, Class<T> clazz) {
		try {
			List<T> l = toList(list, clazz);
			if(l == null) {
				return new ArrayList<>();
			}
			
			return l;
		} catch(Exception e) {
			return new ArrayList<>();
		}
	}
	
	public static <T> List<T> toList(String list, Class<T> clazz) {
		return JSON.parseArray(list, clazz);
	}
	
	public static <T> T getByPath(String text, String deepKey, Class<T> clazz) {
		if(text == null) {
			return null;
		}
		
		JSONObject json = toJSONAnyway(text);
		return getByPath(json, deepKey, clazz);
	}
	
	@SuppressWarnings("unchecked")
	public static <T> T getByPath(JSONObject json, String deepKey, Class<T> clazz) {
		Object o = getByPath(json, deepKey);
		if(o == null) {
			return null;
		}
		
		if(clazz == null) {
			return (T) o;
		}
		
		return typeCast(o, clazz);
	}
	
	public static <T> T getByPath(String text, String path, T defaultValue) {
		JSONObject json = toJSON(text);
		return getByPath(json, path, defaultValue);
	}
	
	public static <T> T getByPath(JSONObject json, String path, T defaultValue) {
		Object o = getByPath(json, path);
		if(o == null) {
			return defaultValue;
		}
		@SuppressWarnings("unchecked")
		Class<T> clazz = (Class<T>) defaultValue.getClass();
		return typeCast(o, clazz);
	}
	
	/**
	 * 根据path或者json的值
	 * TODO: 支持 a.b[0].c 格式
	 * @param json
	 * @param path like a.b.c
	 * @return
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	static Object getByPath(JSONObject json, String path) {
		if(json == null) {
			return null;
		}
		
		if(StringUtils.isBlank(path)) {
			return json;
		}
		
		String[] deep = StringUtils.split(path, ".");
		JSONObject temp = json;
		
		for (int i = 0; i < deep.length; i++) {
			String key = deep[i];
			Object object = temp.get(key);
			
			if(i == deep.length - 1) { //最后一个
				return object;
			}
			
			if(object == null) {
				return null;
			}
			
			if((object instanceof JSONObject)) {
				temp = (JSONObject) object;
			} else if (object instanceof Map) {
				temp = new JSONObject((Map) object);
			} else if (object instanceof String) {
				temp = toJSONAnyway((String) object);
			} else {
				return null;
			}
		}
		
		return null;
	}
	
	@SuppressWarnings("unchecked")
	public static <T> T typeCast(Object object, Class<T> clazz) {
		try {
			if (clazz == JSONObject.class || clazz == JSONArray.class) {
				return (T) JSON.toJSON(object);
			}
			return (T) TypeUtils.cast(object, clazz, ParserConfig.getGlobalInstance());
		} catch (Exception e) {
			return (T) JSON.parseObject(object.toString(), clazz);
		}
	}
	
	public static void main(String[] args) {
		String ext = "{\"store\":{\"masterIcon\":\"https://qtj-dev.oss-cn-hangzhou.aliyuncs.com/resources/20200611/07d8a5cf7b974339b6cccc317f213811.JPG\",\"storeName\":\"北城之一1\",\"id\":1561,\"contactPhone\":\"\",\"phoneNo\":\"18568238271\"},\"user\":{\"headImg\":\"http://thirdwx.qlogo.cn/mmopen/vi_32/DYAIOgq83eoBset0bCY4atoHBH1ibsc8ia8iaZicIzcxz2hFSlxw0yLmicxsiaH5xia4qQYxXsqMibXicicNtt31ialYh2C5Q/132\",\"phone\":\"18568238271\",\"nickName\":\"巴啦啦能量\",\"id\":862}}";
		
		System.out.println(Jsons.getByPath(ext, "store.storeName", ""));
		Object deepGet = Jsons.getByPath(ext, "store.storeName", null);
		System.out.println(deepGet);
		Integer deepGet2 = Jsons.getByPath(ext, "store.storeName2", null);
		System.out.println(deepGet2);
		Object deepGet3 = Jsons.getByPath(ext, "store.storeName2", "");
		System.out.println(deepGet3);
	}
	
}
